home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / src / dokick.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  33.1 KB  |  1,273 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)dokick.c    3.1    93/06/15    */
  2. /* Copyright (c) Izchak Miller, Mike Stephenson, Steve Linhart, 1989. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6. #include "eshk.h"
  7.  
  8. #ifndef POLYSELF
  9. # define martial()    (pl_character[0] == 'S' || pl_character[0] == 'P')
  10. #else
  11. # define is_bigfoot(x)    ((x) == &mons[PM_SASQUATCH])
  12. # define martial()    (pl_character[0] == 'S' || pl_character[0] == 'P' \
  13.              || is_bigfoot(uasmon))
  14. #endif
  15.  
  16. static NEARDATA struct rm *maploc;
  17.  
  18. extern boolean notonhead;    /* for long worms */
  19.  
  20. static void FDECL(kickdmg, (struct monst *, BOOLEAN_P));
  21. static void FDECL(kick_monster, (XCHAR_P, XCHAR_P));
  22. static int FDECL(kick_object, (XCHAR_P, XCHAR_P));
  23. static char *NDECL(kickstr);
  24. static void FDECL(otransit_msg, (struct obj *, XCHAR_P, BOOLEAN_P, int));
  25. static const char *FDECL(gate_str, (XCHAR_P));
  26. static void FDECL(drop_to, (coord *, XCHAR_P));
  27.  
  28. static NEARDATA struct obj *kickobj;
  29.  
  30. #define IS_SHOP(x)    (rooms[x].rtype >= SHOPBASE)
  31.  
  32. static void
  33. kickdmg(mon, clumsy)
  34. register struct monst *mon;
  35. register boolean clumsy;
  36. {
  37.     register int mdx, mdy;
  38.     register int dmg = ( ACURRSTR + ACURR(A_DEX) + ACURR(A_CON) )/ 15;
  39.  
  40.     /* excessive wt affects dex, so it affects dmg */
  41.     if(clumsy) dmg = dmg/2;
  42.  
  43.     /* kicking a dragon or an elephant will not harm it */
  44.     if(thick_skinned(mon->data)) dmg = 0;
  45.  
  46.     /* a good kick exercises your dex */
  47.     exercise(A_DEX, TRUE);
  48.  
  49. /*    it is unchivalrous to attack the defenseless or from behind */
  50.     if (pl_character[0] == 'K' &&
  51.         u.ualign.type == A_LAWFUL && u.ualign.record > -10 &&
  52.         (!mon->mcanmove || mon->msleep || mon->mflee))
  53.         adjalign(-1);
  54.  
  55.     /* squeeze some guilt feelings... */
  56.     if(mon->mtame) {
  57.         abuse_dog(mon);
  58.         mon->mflee = mon->mtame ? 1 : 0;
  59. #ifdef HISX
  60.         mon->mfleetim = mon->mfleetim + (dmg ? rnd(dmg) : 1);
  61. #else
  62.         mon->mfleetim += (dmg ? rnd(dmg) : 1);
  63. #endif
  64.     }
  65.  
  66.     if (dmg > 0)
  67.         mon->mhp -= (!martial() ? rnd(dmg) :
  68.             rnd(dmg)+rnd(ACURR(A_DEX)/2));
  69.     if(mon->mhp < 1) {
  70.         (void) passive(mon, TRUE, 0, TRUE);
  71.         killed(mon);
  72.         return;
  73.     }
  74.     if(martial() && !bigmonst(mon->data) && !rn2(3) && mon->mcanmove
  75.        && mon != u.ustuck) {
  76.         /* see if the monster has a place to move into */
  77.         mdx = mon->mx + u.dx;
  78.         mdy = mon->my + u.dy;
  79.         if(goodpos(mdx, mdy, mon, mon->data)) {
  80.             pline("%s reels from the blow.", Monnam(mon));
  81.             remove_monster(mon->mx, mon->my);
  82.             newsym(mon->mx, mon->my);
  83.             place_monster(mon, mdx, mdy);
  84.             newsym(mon->mx, mon->my);
  85.             set_apparxy(mon);
  86.         }
  87.     }
  88.     (void) passive(mon, FALSE, 1, TRUE);
  89.  
  90. }
  91.  
  92. static void
  93. kick_monster(x, y)
  94. register xchar x, y;
  95. {
  96.     register boolean clumsy = FALSE;
  97.     register struct monst *mon = m_at(x, y);
  98.     register int i, j;
  99.  
  100.     bhitpos.x = x;
  101.     bhitpos.y = y;
  102.     if(special_case(mon)) return;
  103.     setmangry(mon);
  104. #ifdef POLYSELF
  105.     /* Kick attacks by kicking monsters are normal attacks, not special.
  106.      * If you have >1 kick attack, you get all of them.
  107.      */
  108.     if (attacktype(uasmon, AT_KICK)) {
  109.         schar tmp = find_roll_to_hit(mon);
  110.         for(i=0; i<NATTK; i++) {
  111.         if (uasmon->mattk[i].aatyp == AT_KICK && multi >= 0) {
  112.             /* check multi; maybe they had 2 kicks and the first */
  113.             /* was a kick against a floating eye */
  114.             if (tmp > rnd(20)) {
  115.             int sum;
  116.  
  117.             You("kick %s.", mon_nam(mon));
  118.             sum = damageum(mon, &(uasmon->mattk[i]));
  119.             if (sum == 2)
  120.                 (void)passive(mon, 1, 0, TRUE);
  121.             else (void)passive(mon, sum, 1, TRUE);
  122.             } else {
  123.             missum(mon, &(uasmon->mattk[i]));
  124.             (void)passive(mon, 0, 1, TRUE);
  125.             }
  126.         }
  127.         }
  128.         return;
  129.     }
  130. #endif
  131.  
  132.     /* no need to check POLYSELF since only ghosts, which you can't turn */
  133.     /* into, are noncorporeal */
  134.     if(noncorporeal(mon->data)) {
  135.         Your("kick passes through!");
  136.         return;
  137.     }
  138.  
  139.     if(Levitation && !rn2(3) && verysmall(mon->data) &&
  140.        !is_flyer(mon->data)) {
  141.         pline("Floating in the air, you miss wildly!");
  142.         exercise(A_DEX, FALSE);
  143.         (void) passive(mon, FALSE, 1, TRUE);
  144.         return;
  145.     }
  146.  
  147.     i = -inv_weight();
  148.     j = weight_cap();
  149.  
  150.     if(i < (j*3)/10) {
  151.         if(!rn2((i < j/10) ? 2 : (i < j/5) ? 3 : 4)) {
  152.             if(martial() && !rn2(2)) goto doit;
  153.             Your("clumsy kick does no damage.");
  154.             (void) passive(mon, FALSE, 1, TRUE);
  155.             return;
  156.         }
  157.         if(i < j/10) clumsy = TRUE;
  158.         else if(!rn2((i < j/5) ? 2 : 3)) clumsy = TRUE;
  159.     }
  160.  
  161.     if(Fumbling) clumsy = TRUE;
  162.  
  163.     else if(uarm && objects[uarm->otyp].oc_bulky && ACURR(A_DEX) < rnd(25))
  164.         clumsy = TRUE;
  165. doit:
  166.     You("kick %s.", mon_nam(mon));
  167.     if(!rn2(clumsy ? 3 : 4) && (clumsy || !bigmonst(mon->data)) &&
  168.        mon->mcansee && !mon->mtrapped && !thick_skinned(mon->data) &&
  169.        mon->data->mlet != S_EEL && haseyes(mon->data) && mon->mcanmove &&
  170.        !mon->mstun && !mon->mconf && !mon->msleep &&
  171.        mon->data->mmove >= 12) {
  172.         if(!nohands(mon->data) && !rn2(martial() ? 5 : 3)) {
  173.             pline("%s blocks your %skick.", Monnam(mon),
  174.                 clumsy ? "clumsy " : "");
  175.             (void) passive(mon, FALSE, 1, TRUE);
  176.             return;
  177.         } else {
  178.             mnexto(mon);
  179.             if(mon->mx != x || mon->my != y) {
  180.             pline("%s %s, %s evading your %skick.", Monnam(mon),
  181.                 (can_teleport(mon->data) ? "teleports" :
  182.                  is_floater(mon->data) ? "floats" :
  183.                  is_flyer(mon->data) ? "flutters" :
  184.                  nolimbs(mon->data) ? "slides" :
  185.                  "jumps"),
  186.                 clumsy ? "easily" : "nimbly",
  187.                 clumsy ? "clumsy " : "");
  188.             (void) passive(mon, FALSE, 1, TRUE);
  189.             return;
  190.             }
  191.         }
  192.     }
  193.     kickdmg(mon, clumsy);
  194. }
  195.  
  196. /*
  197.  *  Return TRUE if caught (the gold taken care of), FALSE otherwise.
  198.  *  The gold object is *not* attached to the fobj chain!
  199.  */
  200. boolean
  201. ghitm(mtmp, gold)
  202. register struct monst *mtmp;
  203. register struct obj *gold;
  204. {
  205.     if(!likes_gold(mtmp->data) && !mtmp->isshk && !mtmp->ispriest
  206. #ifdef ARMY
  207.         && !is_mercenary(mtmp->data)
  208. #endif
  209.         ) {
  210.         wakeup(mtmp);
  211.     } else if (!mtmp->mcanmove) {
  212.         /* too light to do real damage */
  213.         if (canseemon(mtmp))
  214.             pline("The gold hits %s.", mon_nam(mtmp));
  215.     } else {
  216.         mtmp->msleep = 0;
  217.         mtmp->meating = 0;
  218.         if(!rn2(4)) setmangry(mtmp); /* not always pleasing */
  219.  
  220.         /* greedy monsters catch gold */
  221.         if (cansee(mtmp->mx, mtmp->my))
  222.             pline("%s catches the gold.", Monnam(mtmp));
  223.         mtmp->mgold += gold->quan;
  224.         if (mtmp->isshk) {
  225.             long robbed = ESHK(mtmp)->robbed;
  226.  
  227.             if (robbed) {
  228.                 robbed -= gold->quan;
  229.                 if (robbed < 0) robbed = 0;
  230.                 pline("The amount %scovers %s recent losses.",
  231.                       !robbed ? "" : "partially ",
  232.                       his[mtmp->female]);
  233.                 ESHK(mtmp)->robbed = robbed;
  234.                 if(!robbed)
  235.                     make_happy_shk(mtmp, FALSE);
  236.             } else {
  237.                 if(mtmp->mpeaceful) {
  238.                     ESHK(mtmp)->credit += gold->quan;
  239.                     You("have %ld zorkmid%s in credit.",
  240.                     ESHK(mtmp)->credit,
  241.                     plur(ESHK(mtmp)->credit));
  242.                 } else verbalize("Thanks, scum!");
  243.             }
  244.         }
  245.         else if(mtmp->ispriest) {
  246.             if(mtmp->mpeaceful)
  247.                 verbalize("Thank you for your contribution.");
  248.             else verbalize("Thanks, scum!");
  249.         }
  250. #ifdef ARMY
  251.         else if (is_mercenary(mtmp->data)) {
  252.             long goldreqd = 0L;
  253.  
  254.             if (rn2(3)) {
  255.             if (mtmp->data == &mons[PM_SOLDIER])
  256.                goldreqd = 100L;
  257.             else if (mtmp->data == &mons[PM_SERGEANT])
  258.                goldreqd = 250L;
  259.             else if (mtmp->data == &mons[PM_LIEUTENANT])
  260.                goldreqd = 500L;
  261.             else if (mtmp->data == &mons[PM_CAPTAIN])
  262.                goldreqd = 750L;
  263.  
  264.             if (goldreqd) {
  265.                if (gold->quan > goldreqd +
  266.                 (u.ugold + u.ulevel*rn2(5))/ACURR(A_CHA))
  267.                 mtmp->mpeaceful = TRUE;
  268.             }
  269.              }
  270.              if (mtmp->mpeaceful)
  271.                 verbalize("That should do.  Now beat it!");
  272.              else verbalize("That's not enough, coward!");
  273.          }
  274. #endif
  275.  
  276.         dealloc_obj(gold);
  277.         return(1);
  278.     }
  279.     return(0);
  280. }
  281.  
  282. static int
  283. kick_object(x, y)
  284. xchar x, y;
  285. {
  286.     int range;
  287.     register struct monst *mon, *shkp;
  288.     register struct obj *otmp;
  289.     struct trap *trap;
  290.     boolean costly, insider, shipit;
  291.     boolean isgold;
  292.  
  293.     /* if a pile, the "top" object gets kicked */
  294.     kickobj = level.objects[x][y];
  295.  
  296.     /* kickobj should always be set due to conditions of call */
  297.     if(!kickobj || kickobj->otyp == BOULDER
  298.             || kickobj == uball || kickobj == uchain)
  299.         return(0);
  300.  
  301.     if((trap = t_at(x,y)) && trap->tseen) {
  302.         if (((trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)
  303. #ifdef POLYSELF
  304.             && !passes_walls(uasmon)
  305. #endif
  306.             ) || trap->ttyp == WEB) {
  307.             You("can't kick something that's in a %s!",
  308.                 trap->ttyp == WEB ? "web" : "pit");
  309.             return(1);
  310.         }
  311.     }
  312.  
  313.     if(Fumbling && !rn2(3)) {
  314.         Your("clumsy kick missed.");
  315.         return(1);
  316.     }
  317.  
  318.     /* range < 2 means the object will not move.    */
  319.     /* maybe dexterity should also figure here.     */
  320.     range = (int)((ACURRSTR)/2 - kickobj->owt/40);
  321.  
  322.     if(martial()) range += rnd(3);
  323.  
  324.     /* Mjollnir is magically too heavy to kick */
  325.     if(kickobj->oartifact == ART_MJOLLNIR) range = 1;
  326.  
  327.     /* see if the object has a place to move into */
  328.     if(!ZAP_POS(levl[x+u.dx][y+u.dy].typ) || closed_door(x+u.dx, y+u.dy))
  329.         range = 1;
  330.  
  331.     costly = ((shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) && 
  332.                              costly_spot(x, y));
  333.     insider = (*u.ushops && inside_shop(u.ux, u.uy) &&
  334.                     *in_rooms(x, y, SHOPBASE) == *u.ushops);
  335.  
  336.     /* a box gets a chance of breaking open here */
  337.     if(Is_box(kickobj)) {
  338.         boolean otrp = kickobj->otrapped;
  339.         struct obj *otmp2, *probj = (struct obj *) 0, *temp;
  340.         long loss = 0L;
  341.  
  342.         if(range < 2) pline("THUD!");
  343.  
  344.         for(otmp = kickobj->cobj; otmp; otmp = otmp2) {
  345.             otmp2 = otmp->nobj;
  346.             if (objects[otmp->otyp].oc_material == GLASS
  347.                 && !obj_resists(otmp, 33, 100)) {
  348.                 You("hear a muffled shatter.");
  349.                 if(costly) loss += stolen_value(otmp, x, y, 
  350.                         (boolean)shkp->mpeaceful, TRUE);
  351.                 if (otmp->quan > 1L)
  352.                     useup(otmp);
  353.                 else {
  354.                     temp = otmp;
  355.                     if (otmp == kickobj->cobj) {
  356.                         kickobj->cobj = otmp->nobj;
  357.                         otmp = (struct obj *) 0;
  358.                     } else {
  359.                         probj->nobj = otmp->nobj;
  360.                         otmp = probj;
  361.                     }
  362.                     obfree(temp, (struct obj *) 0);
  363.                 }
  364.             }
  365.             probj = otmp;
  366.         }
  367.         if(costly && loss) {
  368.             if(!insider) {
  369.                   You("caused %ld zorkmids worth of damage!", loss);
  370.             make_angry_shk(shkp, x, y);
  371.             } else
  372.                 You("owe %s %ld zorkmids for objects destroyed.",
  373.                      mon_nam(shkp), loss);
  374.         }
  375.  
  376.         if (kickobj->olocked) {
  377.             if (!rn2(5) || (martial() && !rn2(2))) {
  378.             You("break open the lock!");
  379.             kickobj->olocked = 0;
  380.             kickobj->obroken = 1;
  381.             if (otrp) (void) chest_trap(kickobj, LEG, FALSE);
  382.             return(1);
  383.             }
  384.         } else {
  385.             if (!rn2(3) || (martial() && !rn2(2))) {
  386.             pline("The lid slams open, then falls shut.");
  387.             if (otrp) (void) chest_trap(kickobj, LEG, FALSE);
  388.             return(1);
  389.             }
  390.         }
  391.         if(range < 2) return(1);
  392.         /* else let it fall through to the next cases... */
  393.     }
  394.  
  395.     /* fragile objects should not be kicked */
  396.     if (breaks(kickobj, FALSE)) return(1);
  397.  
  398.     /* potions get a chance of breaking here */
  399.     if(kickobj->oclass == POTION_CLASS) {
  400.         if(rn2(2)) {
  401.             You("smash %s %s!",
  402.               kickobj->quan == 1L ? "the" : "a", xname(kickobj));
  403.             potionbreathe(kickobj);
  404.             if(costly) {
  405.                 long loss = stolen_value(kickobj, kickobj->ox,
  406.                    kickobj->oy, (boolean)shkp->mpeaceful, TRUE);
  407.             if(loss) {
  408.                 if(insider)
  409.                   You("owe %ld zorkmids for objects destroyed.",
  410.                                               loss);
  411.                 else {
  412.                      You("caused %ld zorkmids worth of damage!", loss);
  413.                       make_angry_shk(shkp, kickobj->ox, 
  414.                                         kickobj->oy);
  415.                 }
  416.             }
  417.             }
  418.             useupf(kickobj);
  419.             return(1);
  420.         }
  421.     }
  422.  
  423.     if(IS_ROCK(levl[x][y].typ)) {
  424.         if ((!martial() && rn2(20) > ACURR(A_DEX))
  425. #ifdef POLYSELF
  426.                 || IS_ROCK(levl[u.ux][u.uy].typ)
  427. #endif
  428.                                 ) {
  429.             if (Blind) pline("It doesn't come loose.");
  430.             else pline("%s do%sn't come loose.",
  431.                 The(distant_name(kickobj, xname)),
  432.                 (kickobj->quan == 1L) ? "es" : "");
  433.             return(!rn2(3) || martial());
  434.         }
  435.         if (Blind) pline("It comes loose.");
  436.         else pline("%s come%s loose.",
  437.                The(distant_name(kickobj, xname)),
  438.                (kickobj->quan == 1L) ? "s" : "");
  439.         freeobj(kickobj);
  440.         newsym(x, y);
  441.         if (costly && (!costly_spot(u.ux, u.uy)
  442.                    || !index(u.urooms, *in_rooms(x, y, SHOPBASE))))
  443.             addtobill(kickobj, FALSE, FALSE, FALSE);
  444.         if(!flooreffects(kickobj,u.ux,u.uy,"fall")) {
  445.             kickobj->nobj = fobj;
  446.             fobj = kickobj;
  447.             place_object(kickobj, u.ux, u.uy);
  448.             stackobj(kickobj);
  449.             newsym(u.ux, u.uy);
  450.         }
  451.         return(1);
  452.     }
  453.  
  454.     isgold = (kickobj->otyp == GOLD_PIECE);
  455.  
  456.     /* too heavy to move.  range is calculated as potential distance from
  457.      * player, so range == 2 means the object may move up to one square
  458.      * from its current position
  459.      */
  460.     if(range < 2 || (isgold && kickobj->quan > 300L)) {
  461.         if(!Is_box(kickobj)) pline("Thump!");
  462.         return(!rn2(3) || martial());
  463.     }
  464.  
  465.     if (kickobj->quan > 1L && !isgold) (void) splitobj(kickobj, 1L);
  466.  
  467.     freeobj(kickobj);
  468.     newsym(x, y);
  469.     mon = bhit(u.dx, u.dy, range, KICKED_WEAPON,
  470.            (int (*)()) 0, (int (*)()) 0, kickobj);
  471.  
  472.     /* a flag to "drop" the object to the next level */
  473.     shipit = (!mon && down_gate(bhitpos.x, bhitpos.y) != -1);
  474.  
  475.     if(mon) {
  476.         notonhead = (mon->mx != bhitpos.x || mon->my != bhitpos.y);
  477.         /* awake monster if sleeping */
  478.         wakeup(mon);
  479.         if(isgold ? ghitm(mon, kickobj) :    /* caught? */
  480.            thitmonst(mon, kickobj))        /* hit? */
  481.         return(1);
  482.     }
  483.     if(costly &&
  484.        (!costly_spot(bhitpos.x,bhitpos.y) || shipit ||
  485.         *in_rooms(bhitpos.x, bhitpos.y, 0) != *in_rooms(x, y, 0))) {
  486.  
  487.         if(shipit && ship_object(kickobj, bhitpos.x, bhitpos.y, costly))
  488.         return(1);
  489.  
  490.         if(isgold)
  491.         costly_gold(x, y, kickobj->quan);
  492.         else if(costly_spot(u.ux, u.uy) &&
  493.             index(u.urooms, *in_rooms(x, y, 0)))
  494.         addtobill(kickobj, FALSE, FALSE, FALSE);
  495.         else (void)stolen_value(kickobj, x, y, FALSE, FALSE);
  496.     }
  497.  
  498.     if(shipit && ship_object(kickobj, bhitpos.x, bhitpos.y, costly))
  499.         return(1);
  500.     if(flooreffects(kickobj,bhitpos.x,bhitpos.y,"fall")) return(1);
  501.     kickobj->nobj = fobj;
  502.     fobj = kickobj;
  503.     place_object(kickobj, bhitpos.x, bhitpos.y);
  504.     stackobj(kickobj);
  505.     newsym(kickobj->ox, kickobj->oy);
  506.     return(1);
  507. }
  508.  
  509. static char *
  510. kickstr()
  511. {
  512.     static NEARDATA char buf[BUFSZ];
  513.  
  514.     if (kickobj) Sprintf(buf, "kicking %s", doname(kickobj));
  515.     else {
  516.       Strcpy(buf, "kicking ");
  517.       if (IS_STWALL(maploc->typ)) Strcat(buf, "a wall");
  518.       else if (IS_ROCK(maploc->typ)) Strcat(buf, "a rock");
  519.       else if (IS_THRONE(maploc->typ)) Strcat(buf, "a throne");
  520. #ifdef SINKS
  521.       else if (IS_SINK(maploc->typ)) Strcat(buf, "a sink");
  522. #endif
  523.       else if (IS_ALTAR(maploc->typ)) Strcat(buf, "an altar");
  524.       else if (IS_DRAWBRIDGE(maploc->typ)) Strcat(buf, "the drawbridge");
  525.       else {
  526.         switch (maploc->typ) {
  527.         case STAIRS:
  528.             Strcat(buf, "the stairs");
  529.             break;
  530.         case LADDER:
  531.             Strcat(buf, "a ladder");
  532.             break;
  533.         default:
  534.             Strcat(buf, "something wierd");
  535.             break;
  536.         }
  537.       }
  538.     }
  539.     return buf;
  540. }
  541.  
  542. int
  543. dokick()
  544. {
  545.     register int x, y;
  546.     int avrg_attrib;
  547.     register struct monst *mtmp;
  548.     s_level *slev;
  549.     boolean no_kick = FALSE;
  550.  
  551. #ifdef POLYSELF
  552.     if (nolimbs(uasmon)) {
  553.         You("have no legs to kick with.");
  554.         no_kick = TRUE;
  555.     } else if (verysmall(uasmon)) {
  556.         You("are too small to do any kicking.");
  557.         no_kick = TRUE;
  558.     } else
  559. #endif
  560.     if (Wounded_legs) {
  561.         Your("%s %s in no shape for kicking.",
  562.               ((Wounded_legs & BOTH_SIDES)==BOTH_SIDES)
  563.             ? (const char *)makeplural(body_part(LEG)) : body_part(LEG),
  564.               ((Wounded_legs & BOTH_SIDES)==BOTH_SIDES) ? "are" : "is");
  565.         no_kick = TRUE;
  566.     } else if (near_capacity() > SLT_ENCUMBER) {
  567.         Your("load is too heavy to balance yourself for a kick.");
  568.         no_kick = TRUE;
  569.     } else if (u.uinwater && !rn2(2)) {
  570.         Your("slow motion kick doesn't hit anything.");
  571.         no_kick = TRUE;
  572.     } else if (u.utrap) {
  573.         switch (u.utraptype) {
  574.             case TT_PIT:
  575.             pline("There's not enough room to kick down here.");
  576.             break;
  577.             case TT_WEB:
  578.             case TT_BEARTRAP:
  579.             You("can't move your %s!", body_part(LEG));
  580.             break;
  581.             default:
  582.             break;
  583.         }
  584.         no_kick = TRUE;
  585.     }
  586.  
  587.     if (no_kick) {
  588.         /* discard direction typeahead, if any */
  589.         display_nhwindow(WIN_MESSAGE, TRUE);    /* --More-- */
  590.         return 0;
  591.     }
  592.  
  593.     if(!getdir(NULL)) return(0);
  594.     if(!u.dx && !u.dy) return(0);
  595.  
  596.     x = u.ux + u.dx;
  597.     y = u.uy + u.dy;
  598.     avrg_attrib = (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3;
  599.  
  600.     if(u.uswallow) {
  601.         switch(rn2(3)) {
  602.         case 0:  You("can't move your %s!", body_part(LEG));
  603.              break;
  604.         case 1:  if (is_animal(u.ustuck->data)) {
  605.                 pline("%s burps loudly.", Monnam(u.ustuck));
  606.                 break;
  607.              }
  608.         default: Your("feeble kick has no effect."); break;
  609.         }
  610.         return(1);
  611.     }
  612.  
  613.     wake_nearby();
  614.     u_wipe_engr(2);
  615.  
  616.     maploc = &levl[x][y];
  617.  
  618.     /* The next four tests should stay in      */
  619.     /* their present order: monsters, objects, */
  620.     /* non-doors, doors.               */
  621.  
  622.     if(MON_AT(x, y)) {
  623.         struct permonst *mdat = m_at(x,y)->data;
  624.         kick_monster(x, y);
  625.         if((Is_airlevel(&u.uz) || Levitation) && flags.move) {
  626.             int range;
  627.  
  628.             range = ((int)uasmon->cwt + (weight_cap() + inv_weight()));
  629.             if (range < 1) range = 1; /* divide by zero avoidance */
  630.             range = (3*(int)mdat->cwt) / range;
  631.  
  632.             if(range < 1) range = 1;
  633.             hurtle(-u.dx, -u.dy, range);
  634.         }
  635.         return(1);
  636.     }
  637.  
  638.     kickobj = (struct obj *)0;
  639.     if (OBJ_AT(x, y) &&
  640.         (!Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
  641.          || sobj_at(BOULDER,x,y))) {
  642.         if(kick_object(x, y)) {
  643.             if(Is_airlevel(&u.uz))
  644.             hurtle(-u.dx, -u.dy, 1); /* assume it's light */
  645.             return(1);
  646.         }
  647.         goto ouch;
  648.     }
  649.  
  650.     if(!IS_DOOR(maploc->typ)) {
  651.         if(maploc->typ == SDOOR) {
  652.             if(!Levitation && rn2(30) < avrg_attrib) {
  653.             pline("Crash!  You kick open a secret door!");
  654.             exercise(A_DEX, TRUE);
  655.             maploc->typ = DOOR;
  656.             if(maploc->doormask & D_TRAPPED) {
  657.                 maploc->doormask = D_NODOOR;
  658.                 b_trapped("door", FOOT);
  659.             } else
  660.                 maploc->doormask = D_ISOPEN;
  661.             if (Blind)
  662.                 feel_location(x,y);    /* we know its gone */
  663.             else
  664.                 newsym(x,y);
  665.             unblock_point(x,y);    /* vision */
  666.             return(1);
  667.             } else goto ouch;
  668.         }
  669.         if(maploc->typ == SCORR) {
  670.             if(!Levitation && rn2(30) < avrg_attrib) {
  671.             pline("Crash!  You kick open a secret passage!");
  672.             exercise(A_DEX, TRUE);
  673.             maploc->typ = CORR;
  674.             if (Blind)
  675.                 feel_location(x,y);    /* we known its gone */
  676.             else
  677.                 newsym(x,y);
  678.             unblock_point(x,y);    /* vision */
  679.             return(1);
  680.             } else goto ouch;
  681.         }
  682.         if(IS_THRONE(maploc->typ)) {
  683.             register int i;
  684.             if(Levitation) goto dumb;
  685.             if((Luck < 0 || maploc->doormask) && !rn2(3)) {
  686.             maploc->typ = ROOM;
  687.             maploc->doormask = 0; /* don't leave loose ends.. */
  688.             mkgold((long)rnd(200), x, y);
  689.             if (Blind)
  690.                 pline("CRASH!  You destroy it.");
  691.             else {
  692.                 pline("CRASH!  You destroy the throne.");
  693.                 newsym(x, y);
  694.             }
  695.             exercise(A_DEX, TRUE);
  696.             return(1);
  697.             } else if(Luck > 0 && !rn2(3) && !maploc->looted) {
  698.             mkgold((long) rn1(201, 300), x, y);
  699.             i = Luck + 1;
  700.             if(i > 6) i = 6;
  701.             while(i--) (void) mkobj_at(GEM_CLASS, x, y, TRUE);
  702.             if (Blind)
  703.                 You("kick something loose!");
  704.             else {
  705.                 You("kick loose some ornamental coins and gems!");
  706.                 newsym(x, y);
  707.             }
  708.             /* prevent endless milking */
  709.             maploc->looted = T_LOOTED;
  710.             return(1);
  711.             } else if (!rn2(4)) {
  712.             if(dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz)) {
  713.                 fall_through(FALSE);
  714.                 return(1);
  715.             } else goto ouch;
  716.             }
  717.             goto ouch;
  718.         }
  719.         if(IS_ALTAR(maploc->typ)) {
  720.             if(Levitation) goto dumb;
  721.             You("kick %s.",(Blind ? "something" : "the altar"));
  722.             if(!rn2(3)) goto ouch;
  723.             altar_wrath(x, y);
  724.             exercise(A_DEX, TRUE);
  725.             return(1);
  726.         }
  727. #ifdef SINKS
  728.         if(IS_SINK(maploc->typ)) {
  729.             if(Levitation) goto dumb;
  730.             if(rn2(5)) {
  731.             if(flags.soundok)
  732.                 pline("Klunk!  The pipes vibrate noisily.");
  733.             else pline("Klunk!");
  734.             exercise(A_DEX, TRUE);
  735.             return(1);
  736.             } else if(!(maploc->looted & S_LPUDDING) && !rn2(3) &&
  737.               !(mons[PM_BLACK_PUDDING].geno &
  738.                 (G_GENOD | G_EXTINCT))) {
  739.             if (Blind)
  740.                 You("hear a gushing sound.");
  741.             else
  742.                 pline("A %s ooze gushes up from the drain!",
  743.                       Hallucination ? hcolor() : Black);
  744.             (void) makemon(&mons[PM_BLACK_PUDDING], x, y);
  745.             exercise(A_DEX, TRUE);
  746.             newsym(x,y);
  747.             maploc->looted |= S_LPUDDING;
  748.             return(1);
  749.             } else if(!(maploc->looted & S_LDWASHER) && !rn2(3) &&
  750. # ifndef POLYSELF
  751.                   poly_gender() != 2 &&
  752. # endif
  753.                   !(mons[poly_gender() == 1 ?
  754.                       PM_INCUBUS : PM_SUCCUBUS].geno &
  755.                   (G_GENOD | G_EXTINCT))) {
  756.             /* can't resist... */
  757.             pline("%s returns!", (Blind ? "Something" :
  758.                             "The dish washer"));
  759.             if (makemon(&mons[poly_gender() == 1 ?
  760.                 PM_INCUBUS : PM_SUCCUBUS], x, y)) newsym(x,y);
  761.             maploc->looted |= S_LDWASHER;
  762.             exercise(A_DEX, TRUE);
  763.             return(1);
  764.             } else if(!rn2(3)) {
  765.             pline("Flupp!  %s.", (Blind ?
  766.                       "You hear a sloshing sound" :
  767.                       "Muddy waste pops up from the drain"));
  768.             if(!(maploc->looted & S_LRING)) { /* once per sink */
  769.                 if (!Blind)
  770.                 You("see a ring shining in its midst.");
  771.                 (void) mkobj_at(RING_CLASS, x, y, TRUE);
  772.                 newsym(x, y);
  773.                 exercise(A_DEX, TRUE);
  774.                 exercise(A_WIS, TRUE);    /* a discovery! */
  775.                 maploc->looted |= S_LRING;
  776.             }
  777.             return(1);
  778.             }
  779.             goto ouch;
  780.         }
  781. #endif
  782.         if (maploc->typ == STAIRS || maploc->typ == LADDER ||
  783.                             IS_STWALL(maploc->typ)) {
  784.             if(!IS_STWALL(maploc->typ) && maploc->ladder == LA_DOWN)
  785.             goto dumb;
  786. ouch:
  787.             pline("Ouch!  That hurts!");
  788.             exercise(A_DEX, FALSE);
  789.             exercise(A_STR, FALSE);
  790.             if (Blind) feel_location(x,y); /* we know we hit it */
  791.             if(!rn2(3)) set_wounded_legs(RIGHT_SIDE, 5 + rnd(5));
  792.             losehp(rnd(ACURR(A_CON) > 15 ? 3 : 5), kickstr(),
  793.             KILLED_BY);
  794.             if(Is_airlevel(&u.uz) || Levitation)
  795.             hurtle(-u.dx, -u.dy, rn1(2,4)); /* assume it's heavy */
  796.             return(1);
  797.         }
  798.         if (is_drawbridge_wall(x,y) >= 0) {
  799.             pline("The drawbridge is unaffected.");
  800.             if(Levitation)
  801.             hurtle(-u.dx, -u.dy, rn1(2,4)); /* it's heavy */
  802.             return(1);
  803.         }
  804.         goto dumb;
  805.     }
  806.  
  807.     if(maploc->doormask == D_ISOPEN ||
  808.        maploc->doormask == D_BROKEN ||
  809.        maploc->doormask == D_NODOOR) {
  810. dumb:
  811.         exercise(A_DEX, FALSE);
  812.         if (martial() || ACURR(A_DEX) >= 16 || rn2(3)) {
  813.             You("kick at empty space.");
  814.         } else {
  815.             pline("Dumb move!  You strain a muscle.");
  816.             exercise(A_STR, FALSE);
  817.             set_wounded_legs(RIGHT_SIDE, 5 + rnd(5));
  818.         }
  819.         if ((Is_airlevel(&u.uz) || Levitation) && rn2(2)) {
  820.             hurtle(-u.dx, -u.dy, 1);
  821.             return 1;        /* you moved, so use up a turn */
  822.         }
  823.         return(0);
  824.     }
  825.  
  826.     /* not enough leverage to kick open doors while levitating */
  827.     if(Levitation) goto ouch;
  828.  
  829.     exercise(A_DEX, TRUE);
  830.     /* door is known to be CLOSED or LOCKED */
  831.     if(rnl(35) < avrg_attrib + (!martial() ? 0 : ACURR(A_DEX))) {
  832.         /* break the door */
  833.         if(maploc->doormask & D_TRAPPED) {
  834.             if (flags.verbose) You("kick the door.");
  835.             exercise(A_STR, FALSE);
  836.             maploc->doormask = D_NODOOR;
  837.             b_trapped("door", FOOT);
  838.         } else if(ACURR(A_STR) > 18 && !rn2(5) &&
  839.               !*in_rooms(x, y, SHOPBASE)) {
  840.             pline("As you kick the door, it shatters to pieces!");
  841.             exercise(A_STR, TRUE);
  842.             maploc->doormask = D_NODOOR;
  843.         } else {
  844.             pline("As you kick the door, it crashes open!");
  845.             exercise(A_STR, TRUE);
  846.             if(*in_rooms(x, y, SHOPBASE)) {
  847.             add_damage(x, y, 400L);
  848.             pay_for_damage("break");
  849.             }
  850.             maploc->doormask = D_BROKEN;
  851.         }
  852.         if (Blind)
  853.             feel_location(x,y);        /* we know we broke it */
  854.         else
  855.             newsym(x,y);
  856.         unblock_point(x,y);        /* vision */
  857.         if ((slev = Is_special(&u.uz)) && slev->flags.town)
  858.           for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  859.             if((mtmp->data == &mons[PM_WATCHMAN] ||
  860.             mtmp->data == &mons[PM_WATCH_CAPTAIN]) &&
  861.             couldsee(mtmp->mx, mtmp->my) &&
  862.             mtmp->mpeaceful) {
  863.             pline("%s yells:", Amonnam(mtmp));
  864.             verbalize("Halt, thief!  You're under arrest!");
  865.             (void) angry_guards(FALSE);
  866.             break;
  867.             }
  868.           }
  869.     } else {
  870.         if (Blind) feel_location(x,y);    /* we know we hit it */
  871.         exercise(A_STR, TRUE);
  872.         pline("WHAMMM!!!");
  873.         if ((slev = Is_special(&u.uz)) && slev->flags.town)
  874.           for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  875.             if((mtmp->data == &mons[PM_WATCHMAN] ||
  876.           mtmp->data == &mons[PM_WATCH_CAPTAIN]) &&
  877.               couldsee(mtmp->mx, mtmp->my) &&
  878.               mtmp->mpeaceful) {
  879.         
  880.           pline("%s yells:", Amonnam(mtmp));
  881.           if(levl[x][y].looted & D_WARNED) {
  882.             verbalize("Halt, vandal!  You're under arrest!");
  883.             (void) angry_guards(FALSE);
  884.           } else {
  885.             verbalize("Hey, stop damaging that door!");
  886.             levl[x][y].looted |= D_WARNED;
  887.           }
  888.           break;
  889.             }
  890.           }
  891.     }
  892.     return(1);
  893. }
  894.  
  895. static const char *
  896. gate_str(gate)
  897. register xchar gate;
  898. {
  899.     const char *optr;
  900.  
  901.     switch(gate) {
  902.         case 0:
  903.         case 4:  optr = "through the trap door."; break;
  904.         case 1:
  905.         case 3:  optr = "down the stairs."; break;
  906.         case 2:  optr = "down the ladder."; break;
  907.         default: optr = "down out of sight."; break;
  908.     }
  909.     return(optr);
  910. }
  911.  
  912. static
  913. void
  914. drop_to(cc, loc)
  915. coord *cc;
  916. register xchar loc;
  917. {
  918.     switch(loc) {
  919.         case 0: if(In_endgame(&u.uz) || (Is_botlevel(&u.uz) &&
  920.                   !Is_stronghold(&u.uz))) {
  921.             cc->y = 0;
  922.             return;
  923.             }
  924.             if(Is_stronghold(&u.uz)) {
  925.             cc->x = valley_level.dnum;
  926.             cc->y = valley_level.dlevel;
  927.             break;
  928.             } /* else fall to the next cases */
  929.         case 1:
  930.         case 2:
  931.             cc->x = u.uz.dnum;
  932.             cc->y = u.uz.dlevel + 1;
  933.             break;
  934.         case 3:
  935.             cc->x = sstairs.tolev.dnum;
  936.             cc->y = sstairs.tolev.dlevel;
  937.             break;
  938.         default:
  939.             cc->y = 0;
  940.     }
  941. }
  942.  
  943. void
  944. impact_drop(missile, x, y, dlev)
  945. register struct obj *missile;
  946. register xchar x, y, dlev;
  947. {
  948.     xchar toloc;
  949.     register struct obj *obj, *obj2;
  950.     register struct monst *shkp;
  951.     long oct, dct, price, debit, robbed;
  952.     boolean angry, costly, isrock;
  953.     coord cc;
  954.  
  955.     if(!OBJ_AT(x, y)) return;
  956.  
  957.     toloc = down_gate(x, y);
  958.     drop_to(&cc, toloc);
  959.     if (!cc.y) return;
  960.  
  961.     if (dlev) {
  962.         /* send objects next to player falling through trap door.
  963.          * checked in obj_delivery().
  964.          */
  965.         toloc = 4;
  966.         cc.y = dlev;
  967.     }
  968.  
  969.     costly = costly_spot(x, y);
  970.     price = debit = robbed = 0L;
  971.     angry = FALSE;
  972.     shkp = (struct monst *) 0;
  973.     /* if 'costly', we must keep a record of ESHK(shkp) before
  974.      * it undergoes changes through the calls to stolen_value.
  975.      * the angry bit must be reset, if needed, in this fn, since
  976.      * stolen_value is called under the 'silent' flag to avoid
  977.      * unsavory pline repetitions.
  978.      */
  979.     if(costly) {
  980.         if((shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) != 
  981.                                                (struct monst *)0) {
  982.         debit    = ESHK(shkp)->debit;
  983.         robbed    = ESHK(shkp)->robbed;
  984.         angry    = !shkp->mpeaceful;
  985.         }
  986.     }
  987.  
  988.     isrock = (missile && missile->otyp == ROCK);
  989.     oct = dct = 0L;
  990.     for(obj = level.objects[x][y]; obj; obj = obj2) {
  991.         obj2 = obj->nexthere;
  992.         if(obj == missile) continue;
  993.         /* number of objects in the pile */
  994.         oct += obj->quan;
  995.         if(obj == uball || obj == uchain) continue;
  996.         /* boulders can fall too, but rarely & never due to rocks */
  997.         if((isrock && obj->otyp == BOULDER) ||
  998.            rn2(obj->otyp == BOULDER ? 30 : 3)) continue;
  999.         freeobj(obj);
  1000.  
  1001.         if(costly) {
  1002.             price += stolen_value(obj, x, y,
  1003.                 (costly_spot(u.ux, u.uy) &&
  1004.                  index(u.urooms, *in_rooms(x, y, SHOPBASE))),
  1005.                 TRUE);
  1006.             /* set obj->no_charge to 0 */
  1007.             if (Has_contents(obj))
  1008.             picked_container(obj);    /* does the right thing */
  1009.             if (obj->otyp != GOLD_PIECE)
  1010.             obj->no_charge = 0;
  1011.         }
  1012.         obj->nobj = migrating_objs;
  1013.         migrating_objs = obj;
  1014.  
  1015.         obj->ox = cc.x;
  1016.         obj->oy = cc.y;
  1017.         obj->owornmask = (long)toloc;
  1018.  
  1019.         /* number of fallen objects */
  1020.         dct += obj->quan;
  1021.     }
  1022.  
  1023.     if (dct) {    /* at least one object fell */
  1024.         const char *what = (dct == 1L ? "object falls" : "objects fall");
  1025.         if (missile)
  1026.         pline("From the impact, %sother %s.",
  1027.             dct == oct ? "the " : dct == 1L ? "an" : "", what);
  1028.         else
  1029.         if (oct == dct) {
  1030.             pline("%s adjacent %s %s",
  1031.                 dct == 1L ? "The" : "All the",
  1032.                 what, gate_str(toloc));
  1033.         } else {
  1034.             pline("%s adjacent %s %s",
  1035.                 dct == 1L ? "One of the" : "Some of the",
  1036.                 dct == 1L ? "objects falls" : what,
  1037.                 gate_str(toloc));
  1038.         }
  1039.     }
  1040.  
  1041.     if(costly && shkp && price) {
  1042.         if(ESHK(shkp)->robbed > robbed) {
  1043.             You("removed %ld zorkmids worth of goods!", price);
  1044.             if(cansee(shkp->mx, shkp->my)) {
  1045.             if(ESHK(shkp)->customer[0] == 0)
  1046.                 (void) strncpy(ESHK(shkp)->customer,
  1047.                        plname, PL_NSIZ);
  1048.             if(angry)
  1049.                 pline("%s is infuriated!", Monnam(shkp));
  1050.             else pline("\"%s, you are a thief!\"", plname);
  1051.             } else  You("hear a scream, \"Thief!\"");
  1052.             hot_pursuit(shkp);
  1053.             (void) angry_guards(FALSE);
  1054.             return;
  1055.         }
  1056.         if(ESHK(shkp)->debit > debit)
  1057.             You("owe %s %ld zorkmids for goods lost.",
  1058.             Monnam(shkp),
  1059.             (ESHK(shkp)->debit - debit));
  1060.     }
  1061.  
  1062. }
  1063.  
  1064. /* NOTE: ship_object assumes otmp was FREED from fobj or invent.
  1065.  * <x,y> is the point of drop.  otmp is _not_ an <x,y> resident:
  1066.  * otmp is either a kicked, dropped, or thrown object.
  1067.  */
  1068. boolean
  1069. ship_object(otmp, x, y, shop_floor_obj)
  1070. register xchar  x, y;
  1071. register struct obj *otmp;
  1072. register boolean shop_floor_obj;
  1073. {
  1074.     register xchar ox, oy;
  1075.     register xchar toloc = down_gate(x, y);
  1076.     /* toloc -- destination location: */
  1077.         /*    0: rnd loc,
  1078.          *    1: <,
  1079.          *    2: < ladder,
  1080.          *    3: sstairs up
  1081.          *    4: near player (trapdoor)
  1082.          */
  1083.     coord cc;
  1084.     /* objects always fall down ladder, a chance of stay otherwise */
  1085.     register boolean nodrop = (toloc != 2 && rn2(3));
  1086.     register boolean unpaid, container, impact = FALSE;
  1087.     int n = 0;
  1088.  
  1089.     if(!otmp) return(FALSE);
  1090.     if(toloc == -1) return(FALSE);
  1091.  
  1092.     drop_to(&cc, toloc);
  1093.     if(!cc.y) return(FALSE);
  1094.  
  1095.     container = Has_contents(otmp);
  1096.  
  1097.     unpaid = (otmp->unpaid || (container && count_unpaid(otmp->cobj)));
  1098.  
  1099.     if(OBJ_AT(x, y)) {
  1100.         register struct obj *obj;
  1101.  
  1102.         for(obj = level.objects[x][y]; obj; obj = obj->nexthere)
  1103.         if(obj != otmp) n++;
  1104.         if(n) impact = TRUE;
  1105.     }
  1106.  
  1107.     otransit_msg(otmp, toloc, nodrop, n);
  1108.  
  1109.     if(nodrop) {
  1110.         otmp->nobj = fobj;
  1111.         fobj = otmp;
  1112.         place_object(otmp, x, y);
  1113.         stackobj(otmp);
  1114.         newsym(otmp->ox, otmp->oy);
  1115.         if(impact) goto chain_reaction;
  1116.         else return(TRUE);
  1117.     }
  1118.  
  1119.     if(unpaid || shop_floor_obj) {
  1120.         if(unpaid) {
  1121.         subfrombill(otmp, shop_keeper(*u.ushops));
  1122.         (void)stolen_value(otmp, u.ux, u.uy, TRUE, FALSE);
  1123.         } else {
  1124.             ox = otmp->ox;
  1125.         oy = otmp->oy;
  1126.         (void)stolen_value(otmp, ox, oy,
  1127.               (costly_spot(u.ux, u.uy) &&
  1128.                   index(u.urooms, *in_rooms(ox, oy, SHOPBASE))),
  1129.               FALSE);
  1130.         }
  1131.         /* set otmp->no_charge to 0 */
  1132.         if(container)
  1133.             picked_container(otmp); /* happens to do the right thing */
  1134.         if(otmp->otyp != GOLD_PIECE)
  1135.             otmp->no_charge = 0;
  1136.     }
  1137.  
  1138.     otmp->nobj = migrating_objs;
  1139.     migrating_objs = otmp;
  1140.  
  1141.     otmp->ox = cc.x;
  1142.     otmp->oy = cc.y;
  1143.     otmp->owornmask = (long)toloc;
  1144. chain_reaction:
  1145.     if(impact) {
  1146.         /* the objs impacted may be in a shop other than
  1147.          * the one in which the hero is located.  another
  1148.          * check for a shk is made in impact_drop.  it is, e.g.,
  1149.          * possible to kick/throw an object belonging to one
  1150.          * shop into another shop through a gap in the wall,
  1151.          * and cause objects belonging to the other shop to
  1152.          * fall down a trapdoor--thereby getting two shopkeepers
  1153.          * angry at the hero in one shot.
  1154.          */
  1155.         impact_drop(otmp, x, y, 0);
  1156.         newsym(x,y);
  1157.     }
  1158.     return(TRUE);
  1159. }
  1160.  
  1161. void
  1162. obj_delivery()
  1163. {
  1164.     register struct obj *otmp, *otmp0 = (struct obj *)0, *otmp2;
  1165.  
  1166.     for(otmp = migrating_objs; otmp; otmp = otmp2) {
  1167.         otmp2 = otmp->nobj;
  1168.  
  1169.         if(otmp->ox == u.uz.dnum && otmp->oy == u.uz.dlevel) {
  1170.         if(otmp == migrating_objs)
  1171.             migrating_objs = otmp->nobj;
  1172.         else
  1173.             otmp0->nobj = otmp->nobj;
  1174.         otmp->nobj = fobj;
  1175.         fobj = otmp;
  1176.  
  1177.         switch((xchar)otmp->owornmask) {
  1178.             xchar *xlocale, *ylocale;
  1179.  
  1180.             case 1: xlocale = &xupstair; ylocale = &yupstair;
  1181.                 goto common;
  1182.             case 2: xlocale = &xupladder; ylocale = &yupladder;
  1183.                 goto common;
  1184.             case 3: xlocale = &sstairs.sx; ylocale = &sstairs.sy;
  1185.                 goto common;
  1186.             case 4: { /* hero falls down trapdoor with objects */
  1187.                   xchar nx, ny;
  1188.                   int cnt = 0;
  1189.  
  1190.                   do {
  1191.                   nx = u.ux - 1 + rn2(3);
  1192.                   ny = u.uy - 1 + rn2(3);
  1193.                   } while((nx < 1 || nx > COLNO-2 ||
  1194.                        ny < 1 || ny > ROWNO-2 ||
  1195.                        is_pool(nx,ny) || is_lava(nx,ny) ||
  1196.                        !ACCESSIBLE(levl[nx][ny].typ) ||
  1197.                        closed_door(nx, ny)
  1198.                       ) && cnt++ <= 50);
  1199.  
  1200.                   if(cnt >= 50) goto scatter; /* safety */
  1201.                   xlocale = &nx;
  1202.                   ylocale = &ny;
  1203.                 }
  1204. common:
  1205.                 if (*xlocale && *ylocale) {
  1206.                 place_object(otmp, *xlocale, *ylocale);
  1207.                 stackobj(otmp);
  1208.                 break;
  1209.                 } /* else fall through */
  1210.             default:
  1211. scatter:
  1212.                 /* set dummy coordinates because there's no
  1213.                    current position for rloco() to update */
  1214.                 otmp->ox = otmp->oy = 0;
  1215.                 rloco(otmp);
  1216.                 break;
  1217.         }
  1218.         otmp->owornmask = 0L;
  1219.         } else
  1220.         otmp0 = otmp;
  1221.     }
  1222. }
  1223.  
  1224. static void
  1225. otransit_msg(otmp, loc, nodrop, num)
  1226. register struct obj *otmp;
  1227. register xchar loc;
  1228. register boolean nodrop;
  1229. int num;
  1230. {
  1231.     char obuf[BUFSZ];
  1232.  
  1233.     Sprintf(obuf, "%s%s",
  1234.          (otmp->otyp == CORPSE &&
  1235.             type_is_pname(&mons[otmp->corpsenm])) ? "" : "The ",
  1236.          xname(otmp));
  1237.  
  1238.     if(num) { /* means: other objects are impacted */
  1239.         Sprintf(eos(obuf), " hit%s %s object%s",
  1240.               otmp->quan == 1L ? "s" : "",
  1241.               num == 1 ? "another" : "other",
  1242.               num > 1 ? "s" : "");
  1243.         if(nodrop)
  1244.         Sprintf(eos(obuf), " and stop%s.",
  1245.                  otmp->quan == 1L ? "s" : "");
  1246.         else
  1247.         Sprintf(eos(obuf), " and fall%s %s",
  1248.                 otmp->quan == 1L ? "s" : "", gate_str(loc));
  1249.         pline(obuf);
  1250.     } else if(!nodrop)
  1251.         pline("%s fall%s %s", obuf,
  1252.           otmp->quan == 1L ? "s" : "",
  1253.           gate_str(loc));
  1254. }
  1255.  
  1256. xchar
  1257. down_gate(x, y)
  1258. xchar x, y;
  1259. {
  1260.     register struct trap *ttmp = t_at(x, y);
  1261.  
  1262. #ifdef MULDGN    /* this matches the player restriction in goto_level() */
  1263.     if (on_level(&u.uz, &qstart_level) && !ok_to_quest()) return -1;
  1264. #endif
  1265.     if(ttmp && ttmp->ttyp == TRAPDOOR && ttmp->tseen) return 0;
  1266.     if(xdnstair == x && ydnstair == y) return 1;
  1267.     if(xdnladder == x && ydnladder == y) return 2;
  1268.     if(sstairs.sx == x && sstairs.sy == y && !sstairs.up) return 3;
  1269.     return -1;
  1270. }
  1271.  
  1272. /*dokick.c*/
  1273.